package models

import (
	"context"
	"errors"
	"log"
	"strconv"
	"time"

	"gitee.com/laofa1/play/k_conf_mng/kconf_backend/pkg/setting"
)

// GetLock execute lock according to https://redis.io/commands/setnx
func GetLock(lockKey string) error {
	var errMsg string
	switch lockKey {
	case "templateEditLock":
		ctx := context.Background()
		set, err := redisDB.SetNX(ctx, lockKey, time.Now().Add(setting.ConfTemplateEditLockTimeout).Unix()+1, 0).Result()
		if err != nil {
			log.Println(err)
			return err
		}
		if set {
			return nil
		}
		// try to get the key
		ctx = context.Background()
		oldValue, err := redisDB.Get(ctx, lockKey).Result()
		if err != nil {
			log.Println(err)
			return err
		}
		oldExpireTime, err := strconv.Atoi(oldValue)
		if err != nil {
			log.Println(err)
			return err
		}

		// check if it's not expired
		if int64(oldExpireTime) > time.Now().Unix() {
			errMsg = "other user hold the lock"
			log.Println(errMsg)
			return errors.New(errMsg)
		}
		// lock expired and try GETSET
		ctx = context.Background()
		returnedValue, err := redisDB.GetSet(ctx, lockKey, time.Now().Add(setting.ConfTemplateEditLockTimeout).Unix()+1).Result()
		if err != nil {
			log.Println(err)
			return err
		}
		returnedTime, err := strconv.Atoi(returnedValue)
		if err != nil {
			log.Println(err)
			return err
		}
		if returnedTime == oldExpireTime {
			return nil
		}
		errMsg = "other user locked the lock before you"
		return errors.New(errMsg)
	default:
		return errors.New("lockKey: " + lockKey + " not supported")
	}
}

func DeleteLock(lockKey string) error {
	ctx := context.Background()
	err := redisDB.Del(ctx, lockKey).Err()
	if err != nil {
		log.Println(err)
		return err
	}
	return nil
}
